This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

getwd()
[1] "C:/Users/rchaz/Downloads"

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

#analyse du jeu de données MP graminées
#en R cette fois

install.packages("dplyr")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/rchaz/AppData/Local/R/win-library/4.3’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.3/dplyr_1.1.2.zip'
Content type 'application/zip' length 1551420 bytes (1.5 MB)
downloaded 1.5 MB
package ‘dplyr’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\rchaz\AppData\Local\Temp\RtmpAHim9b\downloaded_packages
library(rlang)
library(dplyr)

Attaching package: ‘dplyr’

The following object is masked from ‘package:signal’:

    filter

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
#installation des librairies
install.packages("readxl")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/rchaz/AppData/Local/R/win-library/4.3’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.3/readxl_1.4.3.zip'
Content type 'application/zip' length 1194912 bytes (1.1 MB)
downloaded 1.1 MB
package ‘readxl’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\rchaz\AppData\Local\Temp\RtmpAHim9b\downloaded_packages
install.packages("ggplot2")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/rchaz/AppData/Local/R/win-library/4.3’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.3/ggplot2_3.4.3.zip'
Content type 'application/zip' length 3329305 bytes (3.2 MB)
downloaded 3.2 MB
package ‘ggplot2’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\rchaz\AppData\Local\Temp\RtmpAHim9b\downloaded_packages
install.packages("caret")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/rchaz/AppData/Local/R/win-library/4.3’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.3/caret_6.0-94.zip'
Content type 'application/zip' length 3576720 bytes (3.4 MB)
downloaded 3.4 MB
package ‘caret’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\rchaz\AppData\Local\Temp\RtmpAHim9b\downloaded_packages
install.packages("MASS") 
Error in install.packages : Updating loaded packages
install.packages("reshape2") 
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/rchaz/AppData/Local/R/win-library/4.3’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.3/reshape2_1.4.4.zip'
Content type 'application/zip' length 454253 bytes (443 KB)
downloaded 443 KB
package ‘reshape2’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\rchaz\AppData\Local\Temp\RtmpAHim9b\downloaded_packages
install.packages("reshape") 
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/rchaz/AppData/Local/R/win-library/4.3’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.3/reshape_0.8.9.zip'
Content type 'application/zip' length 170892 bytes (166 KB)
downloaded 166 KB
package ‘reshape’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\rchaz\AppData\Local\Temp\RtmpAHim9b\downloaded_packages
install.packages("signal") 
Error in install.packages : Updating loaded packages
#Load required libraries
library(ggplot2)
library(readxl)
library(caret)
Loading required package: lattice

Attaching package: ‘caret’

The following object is masked from ‘package:pls’:

    R2
library(signal)
library(pls)

# Create an empty data frame
df <- data.frame()

# Read the Excel data
data <- read_excel('MPall2000600cm.xlsx')

# Display the first 50 rows of data
head(data, 50)
#49 échantillons... c'st tout ce que j'ai pu retrouver.
#et encore : il y a 10 lignines dedans. Vu qu'on se concentre sur les MP, ça réduit le br d'échantillons à 38...
#on ne peut pas faire une prédiction dans les règles avec si peu. Je ne sais pas si je pourrai même obtenir des performances satisfaisantes ave si peu.

#Ouliers attendus : 9F, FF1, FF3  (6, 7, 8)
# Analyze variable types
variable_types <- table(sapply(data, class))

# Plot pie chart for variable types
pie(variable_types, labels = names(variable_types), main = "Variable Types")

# Get the counts of variable types
variable_counts <- table(sapply(data, class))

# Print the counts of variable types
print(variable_counts)

character   numeric 
        1       737 
library(reshape2)
# Drop rows with indices 6, 7, and 8
data <- data[-c(6, 7, 8), ]

# Display the first 40 rows of data
head(data, 40)
# Drop row index 6
data <- data[-6, ]

# Select columns for X
X <- data[, 12:ncol(data)]

# Select columns for Y in PLS1
Y_pcoum <- data[, 10]
Y_SG <- data[, 7]
Y_syr <- data[, 8]
Y_gua <- data[, 9]
Y_oses <- data[, 2]
Y_LK <- data[, 6]

# Select columns for Y in PLS2
Y <- data[, c(2, 6, 7, 10)]
# Display the first 50 rows of X dataset
head(X, 50)
# Display the first few rows of Y_pcoum column
head(Y, 50)
# Create a heatmap to visualize missing values
install.packages("ggplot2")
Error in install.packages : Updating loaded packages
library(ggplot2)

missing_values <- is.na(data)
missing_values_melted <- melt(missing_values)

ggplot(data = missing_values_melted, aes(x = Var2, y = Var1, fill = value)) +
  geom_tile() +
  scale_fill_manual(values = c("TRUE" = "red", "FALSE" = "white")) +labs(title = "Missing Values Heatmap")

# Drop rows with indices 6, 7, and 8
#data <- data[-c(6, 7, 8), ]

# Display the first 40 rows of data
head(data, 40)
# Drop row index 6
#data <- data[-6, ]

# Select columns for X
X <- data[, 12:ncol(data)]

# Select columns for Y in PLS1
Y_pcoum <- data[, 10]
Y_SG <- data[, 7]
Y_syr <- data[, 8]
Y_gua <- data[, 9]
Y_oses <- data[, 2]
Y_LK <- data[, 6]

# Select columns for Y in PLS2
Y <- data[, c(2, 6, 7, 10)]
# Display the first 50 rows of X dataset
head(X, 50)
# Display the first few rows of Y_pcoum column
head(Y_pcoum, 50)
# Display the first few rows of Y dataset
head(Y)
#proChaine étape : le prétraitement des spectres


# Create a vector for wavelength values
wl <- seq(0, 727, 1)

# Plot the transposed data matrix
matplot(X, type = "l", xlab = "Wavelength", ylab = "Spectral Value", 
        col = 1:ncol(X), lty = 1)

dim(Y)
[1] 35  4
dim(X)
[1]  35 727
# Define the SNV normalization function
snv <- function(input_data) {
  output_data <- matrix(0, nrow = nrow(input_data), ncol = ncol(input_data))
  
  for (i in 1:nrow(input_data)) {
    output_data[i,] <- (input_data[i,] - mean(input_data[i,])) / sd(input_data[i,])
  }
  
  return(output_data)
}

# Convert X to a matrix
X <- as.matrix(X)

# Apply SNV normalization
Xsnv <- snv(X)

# Plot the normalized spectral values
matplot(t(Xsnv), type = "l", xlab = "Wavelength", ylab = "Normalized Spectral Value", 
        col = 1:ncol(Xsnv), lty = 1)

dim(Xsnv)
[1]  35 727
# Load the required library
install.packages("signal") 
Error in install.packages : Updating loaded packages
library(signal)

# Define Savitzky-Golay parameters
window_size <- 17
poly_order <- 2

# Transpose the matrix to work on columns
X_transposed <- t(X)

# Apply the Savitzky-Golay filter for second derivative to columns
X2_transposed <- apply(X_transposed, 2, function(col) {
  deriv_filter <- sgolayfilt(c(rep(0, 8), -2, rep(0, 8)), p = 2, n = 17)
  filtered_col <- convolve(col, deriv_filter, type = "filter")
  return(filtered_col)
})

# Transpose the result back to the original orientation
X2 <- t(X2_transposed)

# Plot the second derivative values
matplot(t(X2), type = "l", xlab = "Wavelength", ylab = "Second Derivative Value", 
        col = 1:ncol(X2), lty = 1)

dim(X2)
[1]  35 711
# Apply the Savitzky-Golay filter for second derivative
X2snv <- snv(X2)
dim(X2snv)
[1]  35 711
#tentons une PLS
library(pls)


# Initialize empty vectors to store results
R2_cal <- numeric()
R2_cv <- numeric()
RMSE_cal <- numeric()
RMSE_cv <- numeric()
Var_cal <- numeric()

Components <- 1:20

# Combine the predictor variables and the response variable into a single data frame
data_df <- data.frame(Y_pcoum = unlist(Y_pcoum), Xsnv)


# Calibration
PLS_pcoum <- plsr(Y_pcoum ~ ., ncomp = 7, data = data_df)
Ypred <- predict(PLS_pcoum, newdata = data_df)
  
# Extract the appropriate dimension of Ypred
Ypred_flat <- Ypred[, 1, ]
  
#reprenons nos calculs
R2 <- cor(Ypred_flat, data_df$Y_pcoum)^2
RMSE <- sqrt(mean((Ypred_flat - data_df$Y_pcoum)^2))
 
#résultats 
cat("Results for 7 components\n")
Results for 7 components
cat("R2:", R2, "\n")
R2: 0.5911774 0.6985943 0.854471 0.9495035 0.9688896 0.9771441 0.9819514 
cat("RMSE:", RMSE, "\n\n")
RMSE: 3.036214 
# Cross-validation
Y_cv <- predict(PLS_pcoum, newdata = data.frame(Xsnv), validation = "CV")

# Extract the appropriate dimension of Ypred
Y_cv_flat <- Y_cv[, 1, ]
  
# Calculate scores
R2_cv2 <- cor(Y_cv_flat, data_df$Y_pcoum)^2
RMSE_cv <- sqrt(mean((Y_cv_flat - data_df$Y_pcoum)^2))
  
# Print the results
cat("Results for 7 components\n")
Results for 7 components
cat("R2_cv2:", R2_cv2, "\n")
R2_cv2: 0.5911774 0.6985943 0.854471 0.9495035 0.9688896 0.9771441 0.9819514 
cat("RMSE_cv:", RMSE_cv, "\n\n")
RMSE_cv: 3.036214 

#tentons une autre aporoche pour la cross validation.

# Calibration
PLS_pcoum <- plsr(Y_pcoum ~ ., ncomp = 7, data = data_df)
Ypred <- predict(PLS_pcoum, newdata = data_df)

# Extract the appropriate dimension of Ypred
Ypred_flat <- Ypred[, 1, ]

# Perform manual cross-validation
set.seed(123)  # For reproducibility
num_samples <- nrow(data_df)
num_folds <- 10
fold_size <- num_samples / num_folds

# Initialize vectors to store cross-validation results
R2_cv <- numeric()
RMSE_cv <- numeric()

for (fold in 1:num_folds) {
  # Divide data into training and validation sets
  val_start <- ((fold - 1) * fold_size) + 1
  val_end <- fold * fold_size
  val_indices <- val_start:val_end
  train_indices <- setdiff(1:num_samples, val_indices)
  
  # Fit PLS model on training data
  PLS_pcoum_fold <- plsr(Y_pcoum ~ ., ncomp = 7, data = data_df[train_indices, ])
  
  # Predict on validation data
  Y_cv_fold <- predict(PLS_pcoum_fold, newdata = data_df[val_indices, ])
  
  # Extract the appropriate dimension of Y_cv_fold
  Y_cv_flat <- Y_cv_fold[, 1, ]
  
  # Calculate scores for this fold
  R2_cv_fold <- cor(Y_cv_flat, data_df$Y_pcoum[val_indices])^2
  RMSE_cv_fold <- sqrt(mean((Y_cv_flat - data_df$Y_pcoum[val_indices])^2))
  
  # Store the results for this fold
  R2_cv <- c(R2_cv, R2_cv_fold)
  RMSE_cv <- c(RMSE_cv, RMSE_cv_fold)
}


# Calculate average R2 for cross-validation
average_R2_cv <- mean(R2_cv)

# Calculate average RMSE for cross-validation
average_RMSE_cv <- mean(RMSE_cv)

# Print the cross-validation results
cat("Cross-validation results:\n")
Cross-validation results:
cat("R2_cv:", average_R2_cv, "\n")
R2_cv: 0.7519379 
cat("RMSE_cv:", average_RMSE_cv, "\n")
RMSE_cv: 2.781517 
#j'arrete le script ici. Mon objectif est de monter que je peux traduire un script python en R.
#Le reste du script étant de la PLS sur d'autres paramètres et avec les spectres dérivés, c'est assez répétitif.
#
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiANCmBgYHtyfQ0KZ2V0d2QoKQ0KYGBgDQoNCg0KQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLg0KDQpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4NCg0KVGhlIHByZXZpZXcgc2hvd3MgeW91IGEgcmVuZGVyZWQgSFRNTCBjb3B5IG9mIHRoZSBjb250ZW50cyBvZiB0aGUgZWRpdG9yLiBDb25zZXF1ZW50bHksIHVubGlrZSAqS25pdCosICpQcmV2aWV3KiBkb2VzIG5vdCBydW4gYW55IFIgY29kZSBjaHVua3MuIEluc3RlYWQsIHRoZSBvdXRwdXQgb2YgdGhlIGNodW5rIHdoZW4gaXQgd2FzIGxhc3QgcnVuIGluIHRoZSBlZGl0b3IgaXMgZGlzcGxheWVkLg0KYGBge3J9DQojYW5hbHlzZSBkdSBqZXUgZGUgZG9ubsOpZXMgTVAgZ3JhbWluw6llcw0KI2VuIFIgY2V0dGUgZm9pcw0KDQppbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpDQpsaWJyYXJ5KHJsYW5nKQ0KbGlicmFyeShkcGx5cikNCg0KI2luc3RhbGxhdGlvbiBkZXMgbGlicmFpcmllcw0KaW5zdGFsbC5wYWNrYWdlcygicmVhZHhsIikNCmluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KaW5zdGFsbC5wYWNrYWdlcygiY2FyZXQiKQ0KaW5zdGFsbC5wYWNrYWdlcygiTUFTUyIpIA0KaW5zdGFsbC5wYWNrYWdlcygicmVzaGFwZTIiKSANCmluc3RhbGwucGFja2FnZXMoInJlc2hhcGUiKSANCmluc3RhbGwucGFja2FnZXMoInNpZ25hbCIpIA0KDQojTG9hZCByZXF1aXJlZCBsaWJyYXJpZXMNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkoc2lnbmFsKQ0KbGlicmFyeShwbHMpDQoNCiMgQ3JlYXRlIGFuIGVtcHR5IGRhdGEgZnJhbWUNCmRmIDwtIGRhdGEuZnJhbWUoKQ0KDQojIFJlYWQgdGhlIEV4Y2VsIGRhdGENCmRhdGEgPC0gcmVhZF9leGNlbCgnTVBhbGwyMDAwNjAwY20ueGxzeCcpDQoNCiMgRGlzcGxheSB0aGUgZmlyc3QgNTAgcm93cyBvZiBkYXRhDQpoZWFkKGRhdGEsIDUwKQ0KYGBgDQoNCg0KYGBge3J9DQojNDkgw6ljaGFudGlsbG9ucy4uLiBjJ3N0IHRvdXQgY2UgcXVlIGonYWkgcHUgcmV0cm91dmVyLg0KI2V0IGVuY29yZSA6IGlsIHkgYSAxMCBsaWduaW5lcyBkZWRhbnMuIFZ1IHF1J29uIHNlIGNvbmNlbnRyZSBzdXIgbGVzIE1QLCDDp2EgcsOpZHVpdCBsZSBiciBkJ8OpY2hhbnRpbGxvbnMgw6AgMzguLi4NCiNvbiBuZSBwZXV0IHBhcyBmYWlyZSB1bmUgcHLDqWRpY3Rpb24gZGFucyBsZXMgcsOoZ2xlcyBhdmVjIHNpIHBldS4gSmUgbmUgc2FpcyBwYXMgc2kgamUgcG91cnJhaSBtw6ptZSBvYnRlbmlyIGRlcyBwZXJmb3JtYW5jZXMgc2F0aXNmYWlzYW50ZXMgYXZlIHNpIHBldS4NCg0KI091bGllcnMgYXR0ZW5kdXMgOiA5RiwgRkYxLCBGRjMgICg2LCA3LCA4KQ0KDQpgYGANCmBgYHtyfQ0KIyBBbmFseXplIHZhcmlhYmxlIHR5cGVzDQp2YXJpYWJsZV90eXBlcyA8LSB0YWJsZShzYXBwbHkoZGF0YSwgY2xhc3MpKQ0KDQojIFBsb3QgcGllIGNoYXJ0IGZvciB2YXJpYWJsZSB0eXBlcw0KcGllKHZhcmlhYmxlX3R5cGVzLCBsYWJlbHMgPSBuYW1lcyh2YXJpYWJsZV90eXBlcyksIG1haW4gPSAiVmFyaWFibGUgVHlwZXMiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBHZXQgdGhlIGNvdW50cyBvZiB2YXJpYWJsZSB0eXBlcw0KdmFyaWFibGVfY291bnRzIDwtIHRhYmxlKHNhcHBseShkYXRhLCBjbGFzcykpDQoNCiMgUHJpbnQgdGhlIGNvdW50cyBvZiB2YXJpYWJsZSB0eXBlcw0KcHJpbnQodmFyaWFibGVfY291bnRzKQ0KYGBgDQpgYGB7cn0NCmxpYnJhcnkocmVzaGFwZTIpDQpgYGANCg0KDQpgYGB7cn0NCiMgRHJvcCByb3dzIHdpdGggaW5kaWNlcyA2LCA3LCBhbmQgOA0KZGF0YSA8LSBkYXRhWy1jKDYsIDcsIDgpLCBdDQoNCiMgRGlzcGxheSB0aGUgZmlyc3QgNDAgcm93cyBvZiBkYXRhDQpoZWFkKGRhdGEsIDQwKQ0KYGBgDQoNCmBgYHtyfQ0KIyBEcm9wIHJvdyBpbmRleCA2DQpkYXRhIDwtIGRhdGFbLTYsIF0NCg0KIyBTZWxlY3QgY29sdW1ucyBmb3IgWA0KWCA8LSBkYXRhWywgMTI6bmNvbChkYXRhKV0NCg0KIyBTZWxlY3QgY29sdW1ucyBmb3IgWSBpbiBQTFMxDQpZX3Bjb3VtIDwtIGRhdGFbLCAxMF0NCllfU0cgPC0gZGF0YVssIDddDQpZX3N5ciA8LSBkYXRhWywgOF0NCllfZ3VhIDwtIGRhdGFbLCA5XQ0KWV9vc2VzIDwtIGRhdGFbLCAyXQ0KWV9MSyA8LSBkYXRhWywgNl0NCg0KIyBTZWxlY3QgY29sdW1ucyBmb3IgWSBpbiBQTFMyDQpZIDwtIGRhdGFbLCBjKDIsIDYsIDcsIDEwKV0NCg0KYGBgDQoNCg0KYGBge3J9DQojIERpc3BsYXkgdGhlIGZpcnN0IDUwIHJvd3Mgb2YgWCBkYXRhc2V0DQpoZWFkKFgsIDUwKQ0KYGBgDQoNCg0KYGBge3J9DQojIERpc3BsYXkgdGhlIGZpcnN0IGZldyByb3dzIG9mIFlfcGNvdW0gY29sdW1uDQpoZWFkKFksIDUwKQ0KYGBgDQoNCg0KDQoNCg0KYGBge3J9DQojIENyZWF0ZSBhIGhlYXRtYXAgdG8gdmlzdWFsaXplIG1pc3NpbmcgdmFsdWVzDQppbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCmxpYnJhcnkoZ2dwbG90MikNCg0KbWlzc2luZ192YWx1ZXMgPC0gaXMubmEoZGF0YSkNCm1pc3NpbmdfdmFsdWVzX21lbHRlZCA8LSBtZWx0KG1pc3NpbmdfdmFsdWVzKQ0KDQpnZ3Bsb3QoZGF0YSA9IG1pc3NpbmdfdmFsdWVzX21lbHRlZCwgYWVzKHggPSBWYXIyLCB5ID0gVmFyMSwgZmlsbCA9IHZhbHVlKSkgKw0KICBnZW9tX3RpbGUoKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIlRSVUUiID0gInJlZCIsICJGQUxTRSIgPSAid2hpdGUiKSkgK2xhYnModGl0bGUgPSAiTWlzc2luZyBWYWx1ZXMgSGVhdG1hcCIpDQpgYGANCg0KDQpgYGB7cn0NCiMgRHJvcCByb3dzIHdpdGggaW5kaWNlcyA2LCA3LCBhbmQgOA0KI2RhdGEgPC0gZGF0YVstYyg2LCA3LCA4KSwgXQ0KDQojIERpc3BsYXkgdGhlIGZpcnN0IDQwIHJvd3Mgb2YgZGF0YQ0KaGVhZChkYXRhLCA0MCkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBEcm9wIHJvdyBpbmRleCA2DQojZGF0YSA8LSBkYXRhWy02LCBdDQoNCiMgU2VsZWN0IGNvbHVtbnMgZm9yIFgNClggPC0gZGF0YVssIDEyOm5jb2woZGF0YSldDQoNCiMgU2VsZWN0IGNvbHVtbnMgZm9yIFkgaW4gUExTMQ0KWV9wY291bSA8LSBkYXRhWywgMTBdDQpZX1NHIDwtIGRhdGFbLCA3XQ0KWV9zeXIgPC0gZGF0YVssIDhdDQpZX2d1YSA8LSBkYXRhWywgOV0NCllfb3NlcyA8LSBkYXRhWywgMl0NCllfTEsgPC0gZGF0YVssIDZdDQoNCiMgU2VsZWN0IGNvbHVtbnMgZm9yIFkgaW4gUExTMg0KWSA8LSBkYXRhWywgYygyLCA2LCA3LCAxMCldDQpgYGANCg0KDQpgYGB7cn0NCiMgRGlzcGxheSB0aGUgZmlyc3QgNTAgcm93cyBvZiBYIGRhdGFzZXQNCmhlYWQoWCwgNTApDQpgYGANCg0KDQpgYGB7cn0NCiMgRGlzcGxheSB0aGUgZmlyc3QgZmV3IHJvd3Mgb2YgWV9wY291bSBjb2x1bW4NCmhlYWQoWV9wY291bSwgNTApDQpgYGANCg0KDQpgYGB7cn0NCiMgRGlzcGxheSB0aGUgZmlyc3QgZmV3IHJvd3Mgb2YgWSBkYXRhc2V0DQpoZWFkKFkpDQpgYGANCg0KDQpgYGB7cn0NCiNwcm9DaGFpbmUgw6l0YXBlIDogbGUgcHLDqXRyYWl0ZW1lbnQgZGVzIHNwZWN0cmVzDQoNCg0KIyBDcmVhdGUgYSB2ZWN0b3IgZm9yIHdhdmVsZW5ndGggdmFsdWVzDQp3bCA8LSBzZXEoMCwgNzI3LCAxKQ0KDQojIFBsb3QgdGhlIHRyYW5zcG9zZWQgZGF0YSBtYXRyaXgNCm1hdHBsb3QoWCwgdHlwZSA9ICJsIiwgeGxhYiA9ICJXYXZlbGVuZ3RoIiwgeWxhYiA9ICJTcGVjdHJhbCBWYWx1ZSIsIA0KICAgICAgICBjb2wgPSAxOm5jb2woWCksIGx0eSA9IDEpDQpgYGANCg0KDQpgYGB7cn0NCmRpbShZKQ0KYGBgDQoNCg0KYGBge3J9DQpkaW0oWCkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBEZWZpbmUgdGhlIFNOViBub3JtYWxpemF0aW9uIGZ1bmN0aW9uDQpzbnYgPC0gZnVuY3Rpb24oaW5wdXRfZGF0YSkgew0KICBvdXRwdXRfZGF0YSA8LSBtYXRyaXgoMCwgbnJvdyA9IG5yb3coaW5wdXRfZGF0YSksIG5jb2wgPSBuY29sKGlucHV0X2RhdGEpKQ0KICANCiAgZm9yIChpIGluIDE6bnJvdyhpbnB1dF9kYXRhKSkgew0KICAgIG91dHB1dF9kYXRhW2ksXSA8LSAoaW5wdXRfZGF0YVtpLF0gLSBtZWFuKGlucHV0X2RhdGFbaSxdKSkgLyBzZChpbnB1dF9kYXRhW2ksXSkNCiAgfQ0KICANCiAgcmV0dXJuKG91dHB1dF9kYXRhKQ0KfQ0KDQojIENvbnZlcnQgWCB0byBhIG1hdHJpeA0KWCA8LSBhcy5tYXRyaXgoWCkNCg0KIyBBcHBseSBTTlYgbm9ybWFsaXphdGlvbg0KWHNudiA8LSBzbnYoWCkNCg0KIyBQbG90IHRoZSBub3JtYWxpemVkIHNwZWN0cmFsIHZhbHVlcw0KbWF0cGxvdCh0KFhzbnYpLCB0eXBlID0gImwiLCB4bGFiID0gIldhdmVsZW5ndGgiLCB5bGFiID0gIk5vcm1hbGl6ZWQgU3BlY3RyYWwgVmFsdWUiLCANCiAgICAgICAgY29sID0gMTpuY29sKFhzbnYpLCBsdHkgPSAxKQ0KDQpgYGANCmBgYHtyfQ0KZGltKFhzbnYpDQpgYGANCg0KDQpgYGB7cn0NCiMgTG9hZCB0aGUgcmVxdWlyZWQgbGlicmFyeQ0KaW5zdGFsbC5wYWNrYWdlcygic2lnbmFsIikgDQpsaWJyYXJ5KHNpZ25hbCkNCg0KIyBEZWZpbmUgU2F2aXR6a3ktR29sYXkgcGFyYW1ldGVycw0Kd2luZG93X3NpemUgPC0gMTcNCnBvbHlfb3JkZXIgPC0gMg0KDQojIFRyYW5zcG9zZSB0aGUgbWF0cml4IHRvIHdvcmsgb24gY29sdW1ucw0KWF90cmFuc3Bvc2VkIDwtIHQoWCkNCg0KIyBBcHBseSB0aGUgU2F2aXR6a3ktR29sYXkgZmlsdGVyIGZvciBzZWNvbmQgZGVyaXZhdGl2ZSB0byBjb2x1bW5zDQpYMl90cmFuc3Bvc2VkIDwtIGFwcGx5KFhfdHJhbnNwb3NlZCwgMiwgZnVuY3Rpb24oY29sKSB7DQogIGRlcml2X2ZpbHRlciA8LSBzZ29sYXlmaWx0KGMocmVwKDAsIDgpLCAtMiwgcmVwKDAsIDgpKSwgcCA9IDIsIG4gPSAxNykNCiAgZmlsdGVyZWRfY29sIDwtIGNvbnZvbHZlKGNvbCwgZGVyaXZfZmlsdGVyLCB0eXBlID0gImZpbHRlciIpDQogIHJldHVybihmaWx0ZXJlZF9jb2wpDQp9KQ0KDQojIFRyYW5zcG9zZSB0aGUgcmVzdWx0IGJhY2sgdG8gdGhlIG9yaWdpbmFsIG9yaWVudGF0aW9uDQpYMiA8LSB0KFgyX3RyYW5zcG9zZWQpDQoNCiMgUGxvdCB0aGUgc2Vjb25kIGRlcml2YXRpdmUgdmFsdWVzDQptYXRwbG90KHQoWDIpLCB0eXBlID0gImwiLCB4bGFiID0gIldhdmVsZW5ndGgiLCB5bGFiID0gIlNlY29uZCBEZXJpdmF0aXZlIFZhbHVlIiwgDQogICAgICAgIGNvbCA9IDE6bmNvbChYMiksIGx0eSA9IDEpDQpgYGANCmBgYHtyfQ0KZGltKFgyKQ0KYGBgDQoNCg0KYGBge3J9DQojIEFwcGx5IHRoZSBTYXZpdHpreS1Hb2xheSBmaWx0ZXIgZm9yIHNlY29uZCBkZXJpdmF0aXZlDQpYMnNudiA8LSBzbnYoWDIpDQpgYGANCg0KDQpgYGB7cn0NCmRpbShYMnNudikNCmBgYA0KDQoNCmBgYHtyfQ0KI3RlbnRvbnMgdW5lIFBMUw0KbGlicmFyeShwbHMpDQoNCg0KIyBJbml0aWFsaXplIGVtcHR5IHZlY3RvcnMgdG8gc3RvcmUgcmVzdWx0cw0KUjJfY2FsIDwtIG51bWVyaWMoKQ0KUjJfY3YgPC0gbnVtZXJpYygpDQpSTVNFX2NhbCA8LSBudW1lcmljKCkNClJNU0VfY3YgPC0gbnVtZXJpYygpDQpWYXJfY2FsIDwtIG51bWVyaWMoKQ0KDQpDb21wb25lbnRzIDwtIDE6MjANCg0KIyBDb21iaW5lIHRoZSBwcmVkaWN0b3IgdmFyaWFibGVzIGFuZCB0aGUgcmVzcG9uc2UgdmFyaWFibGUgaW50byBhIHNpbmdsZSBkYXRhIGZyYW1lDQpkYXRhX2RmIDwtIGRhdGEuZnJhbWUoWV9wY291bSA9IHVubGlzdChZX3Bjb3VtKSwgWHNudikNCg0KDQojIENhbGlicmF0aW9uDQpQTFNfcGNvdW0gPC0gcGxzcihZX3Bjb3VtIH4gLiwgbmNvbXAgPSA3LCBkYXRhID0gZGF0YV9kZikNCllwcmVkIDwtIHByZWRpY3QoUExTX3Bjb3VtLCBuZXdkYXRhID0gZGF0YV9kZikNCiAgDQojIEV4dHJhY3QgdGhlIGFwcHJvcHJpYXRlIGRpbWVuc2lvbiBvZiBZcHJlZA0KWXByZWRfZmxhdCA8LSBZcHJlZFssIDEsIF0NCiAgDQojcmVwcmVub25zIG5vcyBjYWxjdWxzDQpSMiA8LSBjb3IoWXByZWRfZmxhdCwgZGF0YV9kZiRZX3Bjb3VtKV4yDQpSTVNFIDwtIHNxcnQobWVhbigoWXByZWRfZmxhdCAtIGRhdGFfZGYkWV9wY291bSleMikpDQogDQojcsOpc3VsdGF0cyANCmNhdCgiUmVzdWx0cyBmb3IgNyBjb21wb25lbnRzXG4iKQ0KY2F0KCJSMjoiLCBSMiwgIlxuIikNCmNhdCgiUk1TRToiLCBSTVNFLCAiXG5cbiIpDQoNCg0KIyBDcm9zcy12YWxpZGF0aW9uDQpZX2N2IDwtIHByZWRpY3QoUExTX3Bjb3VtLCBuZXdkYXRhID0gZGF0YS5mcmFtZShYc252KSwgdmFsaWRhdGlvbiA9ICJDViIpDQoNCiMgRXh0cmFjdCB0aGUgYXBwcm9wcmlhdGUgZGltZW5zaW9uIG9mIFlwcmVkDQpZX2N2X2ZsYXQgPC0gWV9jdlssIDEsIF0NCiAgDQojIENhbGN1bGF0ZSBzY29yZXMNClIyX2N2MiA8LSBjb3IoWV9jdl9mbGF0LCBkYXRhX2RmJFlfcGNvdW0pXjINClJNU0VfY3YgPC0gc3FydChtZWFuKChZX2N2X2ZsYXQgLSBkYXRhX2RmJFlfcGNvdW0pXjIpKQ0KICANCiMgUHJpbnQgdGhlIHJlc3VsdHMNCmNhdCgiUmVzdWx0cyBmb3IgNyBjb21wb25lbnRzXG4iKQ0KY2F0KCJSMl9jdjI6IiwgUjJfY3YyLCAiXG4iKQ0KY2F0KCJSTVNFX2N2OiIsIFJNU0VfY3YsICJcblxuIikNCmBgYA0KDQoNCmBgYHtyfQ0KDQojdGVudG9ucyB1bmUgYXV0cmUgYXBwcm9jaGUgcG91ciBsYSBjcm9zcyB2YWxpZGF0aW9uIDogMTAgc2VnbWVudHMuDQoNCiMgQ2FsaWJyYXRpb24NClBMU19wY291bSA8LSBwbHNyKFlfcGNvdW0gfiAuLCBuY29tcCA9IDcsIGRhdGEgPSBkYXRhX2RmKQ0KWXByZWQgPC0gcHJlZGljdChQTFNfcGNvdW0sIG5ld2RhdGEgPSBkYXRhX2RmKQ0KDQojIEV4dHJhY3QgdGhlIGFwcHJvcHJpYXRlIGRpbWVuc2lvbiBvZiBZcHJlZA0KWXByZWRfZmxhdCA8LSBZcHJlZFssIDEsIF0NCg0KIyBQZXJmb3JtIG1hbnVhbCBjcm9zcy12YWxpZGF0aW9uDQpzZXQuc2VlZCgxMjMpICAjIEZvciByZXByb2R1Y2liaWxpdHkNCm51bV9zYW1wbGVzIDwtIG5yb3coZGF0YV9kZikNCm51bV9mb2xkcyA8LSAxMA0KZm9sZF9zaXplIDwtIG51bV9zYW1wbGVzIC8gbnVtX2ZvbGRzDQoNCiMgSW5pdGlhbGl6ZSB2ZWN0b3JzIHRvIHN0b3JlIGNyb3NzLXZhbGlkYXRpb24gcmVzdWx0cw0KUjJfY3YgPC0gbnVtZXJpYygpDQpSTVNFX2N2IDwtIG51bWVyaWMoKQ0KDQpmb3IgKGZvbGQgaW4gMTpudW1fZm9sZHMpIHsNCiAgIyBEaXZpZGUgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB2YWxpZGF0aW9uIHNldHMNCiAgdmFsX3N0YXJ0IDwtICgoZm9sZCAtIDEpICogZm9sZF9zaXplKSArIDENCiAgdmFsX2VuZCA8LSBmb2xkICogZm9sZF9zaXplDQogIHZhbF9pbmRpY2VzIDwtIHZhbF9zdGFydDp2YWxfZW5kDQogIHRyYWluX2luZGljZXMgPC0gc2V0ZGlmZigxOm51bV9zYW1wbGVzLCB2YWxfaW5kaWNlcykNCiAgDQogICMgRml0IFBMUyBtb2RlbCBvbiB0cmFpbmluZyBkYXRhDQogIFBMU19wY291bV9mb2xkIDwtIHBsc3IoWV9wY291bSB+IC4sIG5jb21wID0gNywgZGF0YSA9IGRhdGFfZGZbdHJhaW5faW5kaWNlcywgXSkNCiAgDQogICMgUHJlZGljdCBvbiB2YWxpZGF0aW9uIGRhdGENCiAgWV9jdl9mb2xkIDwtIHByZWRpY3QoUExTX3Bjb3VtX2ZvbGQsIG5ld2RhdGEgPSBkYXRhX2RmW3ZhbF9pbmRpY2VzLCBdKQ0KICANCiAgIyBFeHRyYWN0IHRoZSBhcHByb3ByaWF0ZSBkaW1lbnNpb24gb2YgWV9jdl9mb2xkDQogIFlfY3ZfZmxhdCA8LSBZX2N2X2ZvbGRbLCAxLCBdDQogIA0KICAjIENhbGN1bGF0ZSBzY29yZXMgZm9yIHRoaXMgZm9sZA0KICBSMl9jdl9mb2xkIDwtIGNvcihZX2N2X2ZsYXQsIGRhdGFfZGYkWV9wY291bVt2YWxfaW5kaWNlc10pXjINCiAgUk1TRV9jdl9mb2xkIDwtIHNxcnQobWVhbigoWV9jdl9mbGF0IC0gZGF0YV9kZiRZX3Bjb3VtW3ZhbF9pbmRpY2VzXSleMikpDQogIA0KICAjIFN0b3JlIHRoZSByZXN1bHRzIGZvciB0aGlzIGZvbGQNCiAgUjJfY3YgPC0gYyhSMl9jdiwgUjJfY3ZfZm9sZCkNCiAgUk1TRV9jdiA8LSBjKFJNU0VfY3YsIFJNU0VfY3ZfZm9sZCkNCn0NCg0KDQojIENhbGN1bGF0ZSBhdmVyYWdlIFIyIGZvciBjcm9zcy12YWxpZGF0aW9uDQphdmVyYWdlX1IyX2N2IDwtIG1lYW4oUjJfY3YpDQoNCiMgQ2FsY3VsYXRlIGF2ZXJhZ2UgUk1TRSBmb3IgY3Jvc3MtdmFsaWRhdGlvbg0KYXZlcmFnZV9STVNFX2N2IDwtIG1lYW4oUk1TRV9jdikNCg0KIyBQcmludCB0aGUgY3Jvc3MtdmFsaWRhdGlvbiByZXN1bHRzDQpjYXQoIkNyb3NzLXZhbGlkYXRpb24gcmVzdWx0czpcbiIpDQpjYXQoIlIyX2N2OiIsIGF2ZXJhZ2VfUjJfY3YsICJcbiIpDQpjYXQoIlJNU0VfY3Y6IiwgYXZlcmFnZV9STVNFX2N2LCAiXG4iKQ0KYGBgDQoNCg0KDQoNCg0KYGBge3J9DQojaidhcnJldGUgbGUgc2NyaXB0IGljaS4gTW9uIG9iamVjdGlmIGVzdCBkZSBtb250ZXIgcXVlIGplIHBldXggdHJhZHVpcmUgdW4gc2NyaXB0IHB5dGhvbiBlbiBSLg0KI0xlIHJlc3RlIGR1IHNjcmlwdCDDqXRhbnQgZGUgbGEgUExTIHN1ciBkJ2F1dHJlcyBwYXJhbcOodHJlcyBldCBhdmVjIGxlcyBzcGVjdHJlcyBkw6lyaXbDqXMsIGMnZXN0IGFzc2V6IHLDqXDDqXRpdGlmLg0KIw0K